﻿using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.ComponentModel;
using System.Web;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Utilities;
using System.Net;
using System.IO;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Xsl;
using System.Text;
using Microsoft.Win32;

namespace SwordClient.SwordClientWebPart
{
    public partial class SwordClientWebPartUserControl : UserControl
    {
        private string POSTBACK_EVENT = "RibbonizedSwordClientClick";
        private string loginForm = @"
";
        private string script = @"
var spShowDialog = function() {
    var div = document.createElement('div');
    div.innerHTML = '<button onclick=""__doPostBack('RibbonizedSwordClientClick')"" />';
    var options = {
        html: div,
        title: 'Deposit via SWORD'
    };
    SP.UI.ModalDialog.showModalDialog(options);
};
ExecuteOrDelayUntilScriptLoaded(spShowDialog, 'sp.js');";

        public SwordClientWebPart WebPart { get; set; }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (this.Page.Request["__EVENTTARGET"] == POSTBACK_EVENT)
            {
                ScriptManager.RegisterStartupScript(this, this.GetType(), ClientID, script, true);
                ; // do something
            }
        }

        protected void DepositClick(object sender, EventArgs e)
        {
            SPListItem item = (SPListItem)SPContext.Current.Item;

            string username = txtUsername.Text;
            string password = txtPassword.Password;
            string location = "";

            // clear the login form
            txtUsername.Text = "";
            txtPassword.Attributes.Add("value", "");

            XmlDocument receipt = null;
            SPFile file = null;
            byte[] fileData;

            // list
            try
            {
                SPAttachmentCollection attachments = item.Attachments;
                foreach (string filename in attachments)
                {
                    file = item.ParentList.ParentWeb.GetFile(attachments.UrlPrefix + filename);
                    fileData = file.OpenBinary();
                }
            }
            // document library
            catch
            {
                file = item.File;
                fileData = file.OpenBinary();
            }

            // POST the file content to the SWORD end point
            using (WebClient wc = new WebClient())
            {
                try
                {
                    Uri uri = new Uri(this.WebPart.SwordEndpoint);

                    // Basic auth
                    wc.Credentials = new NetworkCredential(username, password);

                    // HTTP headers
                    //wc.Headers.Add("X-On-Behalf-Of", item["Author"].ToString());
                    wc.Headers.Add("Content-Disposition", "attachment; filename=" + file.Name);
                    wc.Headers.Add("Content-Type", this.WebPart.GetMimeType(file));

                    // send the request
                    byte[] reqData = file.OpenBinary();
                    //byte[] reqData = Encoding.UTF8.GetBytes(xml);
                    byte[] resData = wc.UploadData(uri, "POST", reqData);

                    // parse the Atom receipt response
                    receipt = new XmlDocument();
                    using (MemoryStream stream = new MemoryStream(resData))
                    {
                        receipt.Load(stream);
                    }

                    // Get the new Location
                    location = wc.ResponseHeaders["Location"];
                }
                catch (WebException err)
                {
                    WebResponse response = err.Response;
                    response.GetResponseStream();
                    litResult.Text = "POST " + this.WebPart.SwordEndpoint + ": " + err.Message + ":\n\n";
                    StreamReader readStream = new StreamReader(response.GetResponseStream());
                    Char[] buffer = new Char[256];
                    int c = 0;
                    while ((c = readStream.Read(buffer, 0, 245)) > 0)
                    {
                        String _buffer = new String(buffer, 0, c);
                        litResult.Text += _buffer;
                    }
                    tabResult.Visible = true;
                    return;
                }
            }

            // parse the Atom deposit receipt
            XmlElement root = receipt.DocumentElement;
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(receipt.NameTable);
            nsmgr.AddNamespace("atom", "http://www.w3.org/2005/Atom");
            XmlNodeList nodeList = root.SelectNodes("/atom:entry/atom:link[@rel='edit']", nsmgr);
            XmlNode link = nodeList[0];
            if (link == null)
            {
                throw new Exception("Missing edit link in Atom receipt");
            }

            // get an Atom XML representation of the item
            XmlDocument srcDocument = this.WebPart.GetItemXml(item);
            string xml = srcDocument.OuterXml;
            TextReader textReader = new StringReader(xml);
            XmlReader xmlReader = XmlReader.Create(textReader);
            using (StringWriter textWriter = new Utf8StringWriter())
            {
                XmlWriter xmlWriter = XmlWriter.Create(textWriter);
                this.WebPart.XsltAtomTransform.Transform(xmlReader, xmlWriter);
                xml = textWriter.ToString();
            }

            // update the Atom metadata
            using (WebClient wc = new WebClient())
            {
                XmlAttribute href = link.Attributes["href"];
                Uri uri = new Uri(href.Value);

                try
                {
                    // Basic auth
                    wc.Credentials = new NetworkCredential(username, password);

                    wc.Headers.Add("Content-Type", "application/atom+xml; type=entry");

                    byte[] reqData = Encoding.UTF8.GetBytes(xml);
                    byte[] resData = wc.UploadData(uri, "PUT", reqData);
                }
                catch (WebException err)
                {
                    WebResponse response = err.Response;
                    response.GetResponseStream();
                    litResult.Text = "PUT " + uri + ": " + err.Message + ":\n\n";
                    StreamReader readStream = new StreamReader(response.GetResponseStream());
                    Char[] buffer = new Char[256];
                    int c = 0;
                    while ((c = readStream.Read(buffer, 0, 245)) > 0)
                    {
                        String _buffer = new String(buffer, 0, c);
                        litResult.Text += _buffer;
                    }
                }
            }

            // show the link to the item
            linkDeposit.NavigateUrl = location;
            linkDeposit.Text = location;
            linkDeposit.Visible = true;

            tabForm.Visible = false;
            tabResult.Visible = true;
        }
    }
}
